/**************************************************************************************************************/
/**************************** General ****************************************************************/
/**************************************************************************************************************/

Object.prototype.isEmpty = function() {
  var o = this;
  for(var p in o) {
    if (o[p] != o.constructor.prototype[p])
      return false;
  }
  return true;
}

/* ChessRules 2009 */
var chessRules = {
    version: "0.01"
};

chessRules.rowFromSquare = function(square) {return square >> 3;};

chessRules.colFromSquare = function(square) {return square & 7;};

chessRules.rowColToSquare = function(row, col) {return row * 8 + col;};

chessRules.isDiagonal = function(sq1, sq2) {return Math.abs(chessRules.rowFromSquare(sq1) - 
    chessRules.rowFromSquare(sq2)) == Math.abs(chessRules.colFromSquare(sq1) - 
    chessRules.colFromSquare(sq2));};

chessRules.isSameRow = function(sq1, sq2) {return chessRules.rowFromSquare(sq1) == chessRules.rowFromSquare(sq2);};

chessRules.isSameCol = function(sq1, sq2) {return chessRules.colFromSquare(sq1) == chessRules.colFromSquare(sq2);};

chessRules.squareToAlgebraic = function(square) {
    var row = chessRules.rowFromSquare(square) + 1;
    var col = chessRules.colFromSquare(square);
    return String.fromCharCode(97 + col) + "" + row.toString();
};

chessRules.algebraicToSquare = function(pgnSq) {
    var col = pgnSq.charCodeAt(0) - 97;
    var row = parseInt(pgnSq[1]) - 1;
    return chessRules.rowColToSquare(row, col);
};

chessRules.distance = function(sq1, sq2) {
    var file1 = sq1 & 7;
    var file2 = sq2 & 7;
    var rank1 = sq1 >> 3;
    var rank2 = sq2 >> 3;
    return Math.max(Math.abs(file1 - file2), Math.abs(rank1 - rank2));
    }

/**************************************************************************************************************/
/**************************************************************************************************************/


/**************************************************************************************************************/
/**************************** Bitboard related ****************************************************************/
/**************************************************************************************************************/

chessRules.bbAttacks = {};

chessRules.Bitboard = function(rows) {
    if (!rows)
        this.rows = [0,0,0,0,0,0,0,0];
    else
        this.rows = rows;
    
    };

chessRules.Bitboard.prototype.toString = function() {
    var ret = "";
    for (var y = this.rows.length - 1; y > -1; y--) {
        for (var x = 0; x < 8; x++)    
            ret += (this.rows[y] & (1 << x)) ? "1" : "0";
        ret += "\n";
        }
    return ret;
    };

chessRules.Bitboard.prototype.set = function(square) {
    var curRow = square >> 3;
    this.rows[curRow] += (1 << (square & 7));
    };
    
chessRules.Bitboard.prototype.unset = function(square) {
    var curRow = square >> 3;
//    this.rows[curRow] &= ~(square & 7);
    this.rows[curRow] -= (1 << (square & 7));
    };

chessRules.Bitboard.prototype.any = function() {
    for (var i = 0; i < this.rows.length; i++)
        if (this.rows[i])
            return true;
    return false;
    };

chessRules.Bitboard.prototype.all = function() {
    for (var i = 0; i < this.rows.length; i++)
        if (this.rows[i] != 255)
            return false;
    return true;
    };

chessRules.Bitboard.prototype.get = function(square) {
    var curRow = square >> 3;
    return this.rows[curRow] & (1 << (square & 7)) ? 1 : 0;
    };

/**************************************************************************************************************/
/**************************************************************************************************************/

/**************************************************************************************************************/
/**************************** FEN related ****************************************************************/
/**************************************************************************************************************/

chessRules.defaultFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";

chessRules.FEN = function(fenString) {
    if (!fenString)
        this.fenString = chessRules.defaultFEN;
    else
        this.fenString = fenString;
        
    var fenArray = this.fenString.split(/\s+/);
        
    this.piecePlacement = fenArray[0];
    this.activeColor = fenArray[1];
    this.castlingAvail = fenArray[2];
    this.enPassant = fenArray[3];
    this.halfMoveClock = parseInt(fenArray[4]);
    this.fullMoveNumber = parseInt(fenArray[5]);
    
};

chessRules.FEN.prototype.toString = function() {
    return this.piecePlacement + " " + this.activeColor + " " + this.castlingAvail + " " + this.enPassant + " "
    + this.halfMoveClock + " " + this.fullMoveNumber;
};

chessRules.FEN.prototype.asciiBoard = function() {
    return chessRules.FEN.ppExpand(this.piecePlacement).replace(/(\w{8})/g, "$1\n");
};

chessRules.FEN.ppExpand = function(compressedPP) {
    if (!compressedPP)
        compressedPP = chessRules.defaultFEN.split(/\s+/)[0];
    var expandedPP = compressedPP.replace("/", "", "g");
    expandedPP = expandedPP.replace(/\d/g, (function(matched) {
        var num = parseInt(matched);
        var ret = "";
        for (var i = 0; i < num; i++)
            ret += "0";
        return ret;
     }));      
    return expandedPP;
}; 

chessRules.FEN.ppCompress = function(expandedPP) {
    if (!expandedPP)
        expandedPP = chessRules.FEN.ppExpand();
    var compressedPP = expandedPP.replace(/(\w{8})(?=\w)/g, "$1/");
//    compressedPP = compressedPP.substr(0, compressedPP.length - 1);
    compressedPP = compressedPP.replace(/0{1,8}/g, (function(matched) {
        return matched.length.toString();
     }));
    return compressedPP;
}; 

/**************************************************************************************************************/
/**************************************************************************************************************/

